package com.hongye.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.hongye.app.model.OrderInfoModel;

/**
 * 支付宝相关
 * @author Administrator
 *
 */
public class AlipayUtils{
	
	public static Logger log = Logger.getLogger(AlipayUtils.class);
	public static final String ALIPAY_GATEWAY_URL = "https://mapi.alipay.com/gateway.do";//支付宝网关(新)
	public static final String ALIPAY_AUTH_GATEWAY_URL = "https://openapi.alipay.com/gateway.do";//支付宝授权网关
	public static final String ServicePID = "2088521291779799";//服务端合作身份者ID
	public static final String APPID = "2016112803475093";//移动端开发者的应用ID
	public static final String NOTIFY_URL_SER = "http://120.27.117.192/rbg/alipay/serNotify";//服务器异步回调地址
	public static final String NOTIFY_URL_APP = "http://120.27.117.192/rbg/alipay/appNotify";//APP异步回调地址
	public static final String MD5_KEY = "n7jsrg38hhutxwuzcb97vi4ucvo13qz5";// 商户的秘钥
	public static final String SIGN_TYPE_MD5 = "MD5";
	public static final String SIGN_TYPE_RSA = "RSA";
	public static final String EMAIL = "rebogou2016@163.com";//付款账号
	public static final String ACCOUNT_NAME  = "河北热播购网络科技有限公司";//付款账户名
	public static final String UTF_8 = "utf-8";
	public static final String PUBLIC_ALIPAY_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB";//支付宝公钥
	public static final String PRIVATE_ALIPAY_KEY_PKCS8 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANGoTymQiTfU3EoHy0+T6Nh27adr4Cg6M1qKIehj81xo7soQYuqwNrtf6Y6lXqaBRSDbuOBWrXKJlI61LEoav4SkOpRi4OCbCngO7DAhPwsAREDnJ2tIDdgqwLQyrAFzDY9C1pSAqbR6gWrV0/x3NsqVf9Tk21e298e7nvoFrvRpAgMBAAECgYEAgaYSJgLiR+tSuljtie1ObSXGOuUDvfyXqyKGa137rSaam8vcT4LepapfFL4AtPh1licpwVj4cz7O5hz1IXI/AZjbnVTaUQTfJDw4PSrgDM59u4UDY8CCfhN0hyQlRQy0emAEh3Ym/JTuCIG8kAJef0MdNhhupmXcyhO76YhIRL0CQQD6wr4yemI5MwhztwgnAsIGltSmimfX6vGWnrG4KOhceyDZQpE7eXcOmuI48tz0jbSOccfMlXsC7SkHGQ3dvPw7AkEA1gm3EdXw/hrd65ERso7CR32KqBoGH5B2I+4yGlFQctTdRMo1KyKdxzMG7K3E8N24Qelf51hB9T34KpcO50TbqwJAeu0Cjf4+rmmdCBS+s1j/wnkoL6gDte4flkWfO3caSVO2y6p9RZmKyqcUpPQxatUYoQeX+WuBzPJzvV4D1SJyxwJAaM5rCV3EWvkW79GiY9fJxC3yJmxP0UbwwplRiVeF2CTpkFSfgla6AZ+35U8Vn4hCQGwhXOv3qDnG+jvrvU0XbwJAPO03rIGdfHAI64yagi7Ha296JoEU+pRmOtJ/vZutU/XCPSJAooocED3lNb8b4bXPSlLPWMl1esRjwt3RCoGpBw==";
	public static final String PRIVATE_ALIPAY_KEY = "MIICXAIBAAKBgQDRqE8pkIk31NxKB8tPk+jYdu2na+AoOjNaiiHoY/NcaO7KEGLqsDa7X+mOpV6mgUUg27jgVq1yiZSOtSxKGr+EpDqUYuDgmwp4DuwwIT8LAERA5ydrSA3YKsC0MqwBcw2PQtaUgKm0eoFq1dP8dzbKlX/U5NtXtvfHu576Ba70aQIDAQABAoGBAIGmEiYC4kfrUrpY7YntTm0lxjrlA738l6sihmtd+60mmpvL3E+C3qWqXxS+ALT4dZYnKcFY+HM+zuYc9SFyPwGY251U2lEE3yQ8OD0q4AzOfbuFA2PAgn4TdIckJUUMtHpgBId2JvyU7giBvJACXn9DHTYYbqZl3MoTu+mISES9AkEA+sK+MnpiOTMIc7cIJwLCBpbUpopn1+rxlp6xuCjoXHsg2UKRO3l3DpriOPLc9I20jnHHzJV7Au0pBxkN3bz8OwJBANYJtxHV8P4a3euREbKOwkd9iqgaBh+QdiPuMhpRUHLU3UTKNSsincczBuytxPDduEHpX+dYQfU9+CqXDudE26sCQHrtAo3+Pq5pnQgUvrNY/8J5KC+oA7XuH5ZFnzt3GklTtsuqfUWZisqnFKT0MWrVGKEHl/lrgczyc71eA9UicscCQGjOawldxFr5Fu/RomPXycQt8iZsT9FG8MKZUYlXhdgk6ZBUn4JWugGft+VPFZ+IQkBsIVzr96g5xvo7671NF28CQDztN6yBnXxwCOuMmoIux2tveiaBFPqUZjrSf72brVP1wj0iQKKKHBA95TW/G+G1z0pSz1jJdXrEY8Ld0QqBqQc=";
	public static final String RETURN_URL_APP = "http://120.27.117.192/rbg/alipay/getAccessToken";//APP用户授权获取token的return_url响应地址
	
	
	public AlipayUtils() {
		
	}
	
	/**
	 * 服务器支付到商家
	 * @author liushaomin
	 * 2016年12月9日
	 * @param ordercode	流水号
	 * @param detail_data_email	收款方账号
	 * @param detail_data_name	收款账号姓名
	 * @param detail_data_money	付款金额
	 * @param detail_data_note	备注说明
	 * @return
	 */
	public static String AlipayForService(String ordercode, String detail_data_email, String detail_data_name, double detail_data_money, String detail_data_note){
		Map<String, String> sParaTemp = new HashMap<String, String>();
		String detail_data= ordercode + "^"+ detail_data_email + "^" + detail_data_name+"^"+detail_data_money+"^"+detail_data_note;
		//基本参数
		sParaTemp.put("service", "batch_trans_notify");	//接口名称
		sParaTemp.put("partner", ServicePID);//服务端合作身份者ID
		sParaTemp.put("_input_charset", UTF_8);//参数编码字符集
		sParaTemp.put("notify_url", NOTIFY_URL_SER);//服务器异步通知页面处理地址
		//业务参数
		sParaTemp.put("account_name", ACCOUNT_NAME);	//付款账号名
		sParaTemp.put("detail_data", detail_data);//付款详细数据
//		String batch_no = Utils.getOrderSN();
		sParaTemp.put("batch_no", ordercode);		//TODO 批次号规则未定
		sParaTemp.put("batch_num", "1");				//付款总笔数
		sParaTemp.put("batch_fee", detail_data_money + "");	//付款总金额
		sParaTemp.put("pay_date", Utils.getDate());		//支付日期
		sParaTemp.put("email", EMAIL);//付款账号
		Map<String, String> sPara = buildRequestPara(sParaTemp);
        System.err.println("batch_no 批次号 =====================" + ordercode);
        System.err.println("detail_data 付款详细数据 =====================" + detail_data);
        if(log.isInfoEnabled()){log.info("AlipayForService sPara=" + sPara);}
        String s = HttpUtils.get(ALIPAY_GATEWAY_URL, sPara);
        return s;
	}
	
	/**
	 * 自动退款接口
	 * @author lifuqiang
	 * 2017-2-6
	 * @param order_sn:订单号
	 * @param refund_amount:退款金额
	 */
	public static boolean refund(String order_sn, Object refund_amount){
		AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_AUTH_GATEWAY_URL,APPID,PRIVATE_ALIPAY_KEY_PKCS8,"json",UTF_8,PUBLIC_ALIPAY_KEY,"RSA");
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		request.setBizContent("{" +
		"    \"out_trade_no\":\""+order_sn+"\"," +
		"    \"refund_amount\":"+refund_amount+"," +
		"    \"refund_reason\":\"正常退款\"," +
		"    \"out_request_no\":\""+Utils.getUserNick()+"\"," +
		"    \"operator_id\":\"rbg_001\"," +
		"    \"store_id\":\"rbg_001\"," +
		"    \"terminal_id\":\"rbg_001\"" +
		"  }");
		AlipayTradeRefundResponse response = null;
		try {
			response = alipayClient.execute(request);
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return response.isSuccess();
	}
	
	/**
	 * 服务器支付到商家 异步通知
	 * 验证消息是否是支付宝发出的合法消息
	 * @author liushaomin
	 * 2016年12月13日
	 * @param params
	 * @return
	 */
	public static boolean verify(Map<String, String> params){
		
		return true;
	}
	
	/**
	 * 生成要请求给支付宝的参数数组
	 * @author liushaomin
	 * 2016年12月13日
	 * @param sParaTemp
	 * @return
	 */
   private static Map<String, String> buildRequestPara(Map<String, String> sParaTemp) {
        String mysign = buildRequestMysign(sParaTemp); //生成签名结果
        sParaTemp.put("sign", mysign); //签名结果与签名方式加入请求提交参数组中
        sParaTemp.put("sign_type", SIGN_TYPE_MD5);
        return sParaTemp;
    }
	 
	
	/**
	 * 生成签名结果
	 * @author liushaomin
	 * 2016年12月9日
	 * @param sPara
	 * @return
	 */
	public static String buildRequestMysign(Map<String, String> sPara) {
    	String prestr = createLinkString(sPara); //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        return sign(prestr, MD5_KEY, UTF_8);
    }
	
	  /**
     * 签名字符串
     * @param text 需要签名的字符串
     * @param key 密钥
     * @param input_charset 编码格式
     * @return 签名结果
     */
    public static String sign(String text, String key, String input_charset) {
    	text = text + key;
        return DigestUtils.md5Hex(getContentBytes(text, input_charset));
    }
	
	/**
	 * 支付宝demo
	 * @author liushaomin
	 * 2016年12月9日
	 * @param content
	 * @param charset
	 * @return
	 */
	private static byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }
	
	/**
	 * 加签方法
	 * @author liushaomin
	 * 2016年12月5日
	 * @param sParaTemp 参数列表 key-参数名称 value-参数值
	 * @param privateKey 加签私钥
	 * @param charset 加签字符集
	 * @return
	 */
	public static String Signature(Map<String, String>sParaTemp, String privateKey, String charset) {
		String result = "";
		try {
			result = AlipaySignature.rsaSign(sParaTemp, privateKey, charset);
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 将map中一级value进行encode
	 * @author liushaomin
	 * 2016年12月2日
	 * @param sParaTemp
	 * @return
	 */
	public static Map<String, Object> ValueToEncode(Map<String, String> sParaTemp) {
	  Map<String, Object> result = new HashMap<String, Object>();
		for (String key : sParaTemp.keySet()) {
			String str = Utils.urlEncoder(sParaTemp.get(key).toString(), "UTF-8");
			result.put(key, str);
		}
        return result;
    }
	
	/** 
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = (String) params.get(key);
            if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }
    
    /**
     * app支付 异步返回结果的验签
     * @author liushaomin
     * 2016年12月7日
     * @param paramsMap 待验证的参数
     * @return
     */
    public static boolean signVerified(Map<String, String> paramsMap) {
    	boolean signVerified = true;
		try {
			signVerified = AlipaySignature.rsaCheckV1(paramsMap, PUBLIC_ALIPAY_KEY, paramsMap.get("charset"));//调用SDK验证签名
			System.err.println("异步返回结果的验签signVerified==========" + signVerified);
			if(signVerified){
				//按照支付结果异步通知中的描述，对支付结果中的业务内容进行1\2\3\4二次校验，校验成功后在response中返回success，校验失败返回failure
				//3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
				String ordersn = paramsMap.get("out_trade_no");
				String total_amount = paramsMap.get("total_amount");
				String app_id = paramsMap.get("app_id");
				String subject = paramsMap.get("subject");
				OrderInfoModel order = OrderInfoModel.getOrderBySN(ordersn);
				if (order == null) {//1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
					signVerified = false;
				}
				if(signVerified){//2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）
					if (subject.equals("rebogou")) {//批量订单支付
						double summoney = OrderInfoModel.dao.getTotal_PriceByID(order.getStr("orderids"));
						if(!Double.valueOf(total_amount).equals(summoney)){
							signVerified = false;
						}
					}else{
						if(!order.getFloat("total_price").equals(Float.valueOf(total_amount))){
							signVerified = false;
						}
					}
				}
				if(signVerified){//4、验证app_id是否为该商户本身
					if(!app_id.equals(APPID)){
						signVerified = false;
					}
				}
			}
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
    	return signVerified;
	}

}
